package com.zh.web.base;

import com.zh.common.constant.ExCodeConstant;
import com.zh.common.exception.AuthException;
import com.zh.common.exception.BusinessException;
import com.zh.common.exception.ForbiddenException;
import com.zh.web.baseInterface.BaseControllerInterface;
import com.zh.common.dto.IpDto;
import feign.FeignException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public abstract class AbstractBaseController implements BaseControllerInterface {

    @Override
    public <T> ApiResult<T> buildSuccessPackage(T data) {
        return ApiResult.success(data);
    }

    @Override
    public <T> ApiResult<T> buildMsgPackage(T msg) {
        return ApiResult.msg(msg);
    }

    @Override
    public <T> ApiResult<T> buildFailPackage(String msg) {
        return ApiResult.fail(msg);
    }

    public <T> ApiResult<T> buildFailPackage(String msg, int code) {
        return ApiResult.fail(msg, code);
    }

    @Override
    public ApiResult buildDefaultPackage() {
        return ApiResult.ok();
    }

    /**
     * 业务异常（继承自运行时异常）
     *
     * @param bex 业务异常
     * @return ApiResult<T>
     */
    @ExceptionHandler(BusinessException.class)
    public ApiResult BusinessExceptionHandler(BusinessException bex) {
        log.error(bex.getMessage(), bex);
        return buildFailPackage(bex.getMessage(), ExCodeConstant.BEX_CODE);
    }

    /**
     * 权限相关
     *
     * @param aex 登录异常
     * @return ApiResult<T>
     */
    @ExceptionHandler(AuthException.class)
    public <T> ApiResult<T> AuthExceptionHandler(AuthException aex) {
        log.error(aex.getMessage(), aex);
        return buildFailPackage(aex.getMessage(), ExCodeConstant.UAT_CODE);
    }

    /**
     * 禁止的异常
     *
     * @param aex
     * @return
     */
    @ExceptionHandler(ForbiddenException.class)
    public <T> ApiResult<T> ForbiddenExceptionHandler(ForbiddenException aex) {
        log.error(aex.getMessage(), aex);
        return buildFailPackage(aex.getMessage(), ExCodeConstant.FB_CODE);
    }

    /**
     * 参数异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public <T> ApiResult<T> ExceptionHandler(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        Map<String, String> errors = new HashMap<>();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errors.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        log.error(errors.toString());
        return buildFailPackage(errors.toString(), ExCodeConstant.PARAM_CODE);
    }

    /**
     * 服务不可用
     *
     * @param
     * @return ApiResult<T>
     */
    @ExceptionHandler(FeignException.ServiceUnavailable.class)
    public <T> ApiResult<T> ServiceUnavailableExceptionHandler(FeignException.ServiceUnavailable ex) {
        log.error("服务不可用:" + ex.getMessage(), ex);
        String errmsg = ex.getMessage().split("/")[2] + "服务不可用";
        return buildFailPackage(errmsg);
    }


    /**
     * 空指针异常
     *
     * @param ex 其他异常
     * @return ApiResult<T>
     */
    @ExceptionHandler(NullPointerException.class)
    public <T> ApiResult<T> NullPointExceptionHandler(NullPointerException ex) {
        log.error("异常 {}", ex.getClass(), ex);
        return buildFailPackage(ex.toString());
    }
    /**
     * 其他异常
     *
     * @param ex 其他异常
     * @return ApiResult<T>
     */
    @ExceptionHandler(Exception.class)
    public <T> ApiResult<T> ExceptionHandler(Exception ex) {
        log.error("异常 {}", ex.getClass(), ex);
        return buildFailPackage(ex.getMessage());
    }

    /**
     * 提供一个获取Ip地址的方法
     */
    public abstract IpDto getIpAddress(HttpServletRequest request);
}
